package com.qiwenshare.file.dingding.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.HashUtils;
import com.qiwenshare.file.dingding.constant.DingdingEventTypeConstants;
import com.qiwenshare.file.dingding.service.IDingdingSynService;
import com.qiwenshare.file.domain.dept.DeptBean;
import com.qiwenshare.file.domain.user.UserBean;
import com.qiwenshare.file.mapper.DeptMapper;
import com.qiwenshare.file.mapper.UserMapper;
import com.qiwenshare.file.util.SpringUtils;
import com.qiwenshare.file.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DingdingSynServiceImpl implements IDingdingSynService {

    public static final Logger log = LoggerFactory.getLogger(DingdingSynServiceImpl.class);

    @Autowired
    public DeptMapper deptMapper;

    @Autowired
    public UserMapper userMapper;

//    @Autowired
//    public IDingdingSynService dingdingSynService;

    @Transactional
    @Override
    public String synchronizeDept(List<DeptBean> DeptBeanList) {
        DeptBean topDept = new DeptBean();
        topDept.setParentId(0l);
        topDept.setDdDeptId(1l);
        topDept.setDdParentId(0l);
        topDept.setDeptName("泉州爱斯奇供应链有限公司");
        DeptBeanList.add(topDept);
        // 去重,组织树结构
        List<DeptBean> treeList = new ArrayList<>();

        Map<Long, List<DeptBean>> longListMap = DeptBeanList.stream().collect(Collectors.groupingBy(DeptBean::getDdParentId));
        DeptBeanList.forEach(v->{
            v.setChildren(longListMap.get(v.getDdDeptId()));
        });
        treeList = DeptBeanList.stream().filter(organization-> organization.getDdParentId().equals(0L)).collect(Collectors.toList());

        // 查出所有部门数据
        List<DeptBean> localDeptBeanList = deptMapper.selectDeptList2(new DeptBean());
        Map<Long, DeptBean> longDeptBeanMap = localDeptBeanList.stream().collect(Collectors.toMap(DeptBean::getDdDeptId, d->d, (o, n)-> n));

        // 递归处理各级部门新增更新
//        dingdingSynService.recursionTree(0L, treeList, localDeptBeanList);
        recursionTree(0L, treeList, longDeptBeanMap);

        return "同步成功";
    }

    /**
     * 同步钉钉用户
     * @param users
     * @return
     */
    @Transactional
    @Override
    public String synchronizeUser(List<UserBean> users) {
        // 去重，根据userid分组部门
        Map<String, UserBean> dingdingUsersMap = users.stream().collect(Collectors.toMap(UserBean::getDdUserId, d->d, (o, n)-> n));
        log.info("【钉钉用户同步】去重后用户数:{}", dingdingUsersMap.size());
        // 查询所有本地用户
        List<UserBean> localUsers = userMapper.selectList(new QueryWrapper<>());
        // 考虑重复用户问题：即钉钉上一个用户多部门，UserBean新增部门id列表字段
        Map<String, UserBean> longUserBeanMap = localUsers.stream().collect(Collectors.toMap(UserBean::getDdUserId, d->d, (oldValue, newValue)->newValue));
        // 查询所有部门用户
        List<DeptBean> localDeptList = deptMapper.selectDeptList2(new DeptBean());
        Map<Long, Long> longDeptBeanMap = localDeptList.stream().collect(Collectors.toMap(DeptBean::getDdDeptId, DeptBean::getDeptId, (o, n)->n));
        StringBuilder resultMsg = new StringBuilder();
        // 遍历钉钉用户SecurityUtils.encryptPassword(user.getPassword())
        List<UserBean> addUsers = new ArrayList<>();
        // 本地存在但钉钉不存在的则表示已删除,status设为1停用
        List<UserBean> delUser = new ArrayList<>();
        for (String ddUserId : longUserBeanMap.keySet()) {
            UserBean UserBean = longUserBeanMap.get(ddUserId);
            if (!"admin".equals(UserBean.getUsername())
                    && !StringUtils.isEmpty(UserBean.getDdUserId())
                    && !dingdingUsersMap.containsKey(ddUserId)) {
                delUser.add(UserBean);
            }
        }

        dingdingUsersMap.forEach((ddUserId, user) -> {
            String newDeptIds = "";
            for (String s : user.getDdDeptIds().split(",")) {
                // 有些用户有最顶层部门
                if (Long.valueOf(s).equals(1L)) {
                    newDeptIds += "0,";
                } else {
                    if (longDeptBeanMap.containsKey(Long.valueOf(s))) {
                        newDeptIds += longDeptBeanMap.get(Long.valueOf(s)).toString() + ",";
                    }
                }
            }
            // 若存在部分部门未匹配，也不操作
            if (newDeptIds.split(",").length < user.getDdDeptIds().split(",").length) {
                if (resultMsg.length() == 0) {
                    resultMsg.append("存在部分用户未匹配到本地部门信息，请先同步部门信息后再次同步用户信息");
                }
            } else {
                newDeptIds = "," + newDeptIds;
                user.setDeptIds(newDeptIds.toString());
                user.setDeptId(longDeptBeanMap.get(user.getDdDeptId()));
                // 判断是否存在用户
                boolean exist = false;
                if (longUserBeanMap.containsKey(ddUserId)) {
                    exist = true;
                    UserBean localUser = longUserBeanMap.get(ddUserId);
                    // 判断用户的部门列表是否改变，改变则更新，未改变则不更新
                    if (!user.getDeptIds().equals(localUser.getDeptIds())) {
                        localUser.setDeptIds(user.getDeptIds());
                        localUser.setDeptId(user.getDeptId());
                        localUser.setSalt(null);
                        localUser.setPassword(null);
                        localUser.setNickname(user.getNickname());
                        localUser.setModifyTime(DateUtil.getCurrentTime());
                        userMapper.updateById(localUser);
                        log.info("更新用户:{}", localUser.getNickname());
                    }
                }

                if (!exist) {
                    // 性别未知
                    user.setSex("2");
                    String newPassword = HashUtils.hashHex("MD5", user.getPassword(), user.getSalt(), 1024);
                    user.setPassword(newPassword);
                    user.setRegisterTime(DateUtil.getCurrentTime());
                    user.setUserId(IdUtil.getSnowflakeNextIdStr());
                    addUsers.add(user);

                }
            }

        });
        // 新增用户
        if (!addUsers.isEmpty()) {
            userMapper.insertBatchUsers(addUsers);
            log.info("新增用户:{}", String.join(",", addUsers.stream().map(UserBean::getNickname).collect(Collectors.toList())));
        }
        // 停用用户
        if (!delUser.isEmpty()) {
            userMapper.batchUpdateStatus(delUser);
            log.info("停用用户:{}", String.join(",", delUser.stream().map(UserBean::getNickname).collect(Collectors.toList())));
        }

        return "同步成功";
    }

    @Transactional
    @Override
    public void recursionTree(Long pDeptId, List<DeptBean> treeList, Map<Long, DeptBean> longDeptBeanMap) {
        if (treeList == null) {
            return;
        }
        for (DeptBean DeptBean : treeList) {
            // 顶级部门不需要新增
//            if (DeptBean.getDdDeptId().equals(1l)) {
//                // 遍历子部门
//                recursionTree(pDeptId, DeptBean.getChildren(), longDeptBeanMap);
//                continue;
//            }
            // 子部门是否存在标志
            boolean exist = false;
            // 遍历判断本地部门列表中部门是否存在
            if (longDeptBeanMap.containsKey(DeptBean.getDdDeptId())) {
                DeptBean dept = longDeptBeanMap.get(DeptBean.getDdDeptId());
                exist = true;
                if (!DeptBean.getDdParentId().equals(longDeptBeanMap.get(DeptBean.getDdDeptId()).getDdParentId())) {
                    // 查询修改后的父部门的记录
                    String ancestors = "";
                    String origAncestor = "";
                    DeptBean DeptBean1 = longDeptBeanMap.get(DeptBean.getDdParentId());
                    ancestors = DeptBean1.getAncestors() + "," + DeptBean1.getDeptId();
                    origAncestor = dept.getAncestors();
                    dept.setParentId(DeptBean1.getDeptId());
                    dept.setAncestors(ancestors);
                    // 父部门修改，更新
                    dept.setDdParentId(DeptBean.getDdParentId());
                    dept.setDeptName(DeptBean.getDeptName());
                    dept.setUpdateTime(new Date());
                    // 更新
                    deptMapper.updateDept(dept);
                    List<Long> child = new ArrayList<>();
                    getAllChildDeptId(DeptBean, child, longDeptBeanMap);
                    // 更新子部门
                    if (!child.isEmpty()) {
                        deptMapper.updatePreAncestorsByDeptId(ancestors, origAncestor, child);
                    }
                }
                // 递归
                recursionTree(dept.getDeptId(), DeptBean.getChildren(), longDeptBeanMap);
            }

            if (!exist) {
                // 新增
                DeptBean newDept = new DeptBean();
                newDept.setDdDeptId(DeptBean.getDdDeptId());
                newDept.setDdParentId(DeptBean.getDdParentId());
                newDept.setParentId(pDeptId);
                if (pDeptId.equals(0l)) {
                    newDept.setAncestors(String.valueOf(pDeptId));
                } else {
                    if (longDeptBeanMap.containsKey(pDeptId)) {
                        newDept.setAncestors(longDeptBeanMap.get(pDeptId).getAncestors() + "," + pDeptId);
                    }
                }
                newDept.setDeptName(DeptBean.getDeptName());
                newDept.setStatus("0");
                newDept.setDelFlag("0");
                deptMapper.insertDept(newDept);
                longDeptBeanMap.put(newDept.getDeptId(), newDept);
                // 递归
                recursionTree(newDept.getDeptId(), DeptBean.getChildren(), longDeptBeanMap);
            }
        }
    }

    @Transactional
    @Override
    public void userEventDeal(String eventType, List<UserBean> users) {
        // 查询所有部门用户
        List<DeptBean> localDeptList = deptMapper.selectDeptList2(new DeptBean());
        Map<Long, Long> longDeptBeanMap = localDeptList.stream().collect(Collectors.toMap(DeptBean::getDdDeptId, DeptBean::getDeptId, (o, n)->n));

        if (DingdingEventTypeConstants.USER_ADD_ORG.equals(eventType)) {
            // 查询所有本地用户
            List<UserBean> localUsers = userMapper.selectList(new QueryWrapper<>());
            Map<String, UserBean> localUserMap = localUsers.stream().collect(Collectors.toMap(UserBean::getDdUserId, t->t, (o, n)->n));
            List<UserBean> addUsers = new ArrayList<>();
            users.forEach(user -> {
                // 判断用户是否存在，存在不新增
                if (!localUserMap.containsKey(user.getDdUserId())) {
                    // 判断用户所在部门是否存在
                    String newDeptIds = "";
                    for (String s : user.getDdDeptIds().split(",")) {
                        // 有些用户有最顶层部门
                        if (Long.valueOf(s).equals(1L)) {
                            newDeptIds += "0,";
                        } else {
                            if (longDeptBeanMap.containsKey(Long.valueOf(s))) {
                                newDeptIds += longDeptBeanMap.get(Long.valueOf(s)).toString() + ",";
                            }
                        }
                    }
                    // 若存在部分部门未匹配，也不操作
                    if (newDeptIds.split(",").length < user.getDdDeptIds().split(",").length) {
                        log.info("【钉钉用户新增事件】部分部门未匹配到本地部门信息");
                    }

                    newDeptIds = "," + newDeptIds;
                    user.setDeptIds(newDeptIds.toString());
                    user.setDeptId(longDeptBeanMap.get(user.getDdDeptId()));
                    // 性别未知
                    user.setSex("2");
                    String newPassword = HashUtils.hashHex("MD5", user.getPassword(), user.getSalt(), 1024);
                    user.setPassword(newPassword);
                    user.setUserId(IdUtil.getSnowflakeNextIdStr());
                    addUsers.add(user);
                } else {
                    log.info("【钉钉用户新增事件】用户已存在！");
                }
            });
            if (!addUsers.isEmpty()) {
                userMapper.insertBatchUsers(addUsers);
                log.info("【钉钉用户新增事件】新增成功:{}", JSON.toJSONString(addUsers));
            }
        } else if (DingdingEventTypeConstants.USER_MODIFY_ORG.equals(eventType)) {
            // 判断用户部门是否更新，重新组织部门列表
            // 查询所有本地用户
            List<UserBean> localUsers = userMapper.selectList(new QueryWrapper<>());
            // 考虑重复用户问题：即钉钉上一个用户多部门，UserBean新增部门id列表字段
            Map<String, UserBean> longUserBeanMap = localUsers.stream().collect(Collectors.toMap(UserBean::getDdUserId, d->d, (oldValue, newValue)->newValue));
            users.forEach(user -> {
                if (longUserBeanMap.containsKey(user.getDdUserId())) {
                    // 拼接用户所在部门列表
                    String newDeptIds = "";
                    for (String s : user.getDdDeptIds().split(",")) {
                        // 有些用户有最顶层部门
                        if (Long.valueOf(s).equals(1L)) {
                            newDeptIds += "0,";
                        } else {
                            if (longDeptBeanMap.containsKey(Long.valueOf(s))) {
                                newDeptIds += longDeptBeanMap.get(Long.valueOf(s)).toString() + ",";
                            }
                        }
                    }
                    UserBean origUser = longUserBeanMap.get(user.getDdUserId());
                    newDeptIds = "," + newDeptIds;
                    // 更新部门
                    if (!newDeptIds.equals(origUser.getDeptIds())) {

                        origUser.setDeptIds(newDeptIds.toString());
                        origUser.setDeptId(longDeptBeanMap.get(user.getDdDeptId()));
                        origUser.setTelephone(user.getTelephone());
                        origUser.setEmail(user.getEmail());
                        origUser.setNickname(user.getNickname());
                        origUser.setModifyTime(DateUtil.getCurrentTime());
                        userMapper.updateById(origUser);
                        log.info("【钉钉用户修改事件】用户更新部门成功！{}", JSON.toJSONString(origUser));
                    }
                }
            });
        } else if (DingdingEventTypeConstants.USER_LEAVE_ORG.equals(eventType)) {
            if (!users.isEmpty()) {
                userMapper.batchUpdateStatus(users);
                log.info("【钉钉用户离职事件】用户删除成功！{}", String.join(",", users.stream().map(UserBean::getDdUserId).collect(Collectors.toList())));
            }
        }
    }

    @Transactional
    @Override
    public void deptEventDeal(String eventType, List<DeptBean> depts) {
        // 查出所有部门数据
        List<DeptBean> localDeptBeanList = deptMapper.selectDeptList2(new DeptBean());
        Map<Long, DeptBean> longDeptBeanMap = localDeptBeanList.stream().collect(Collectors.toMap(DeptBean::getDdDeptId, d->d, (o, n)-> n));
        // 子部门
        Map<Long, List<DeptBean>> longListMap = localDeptBeanList.stream().collect(Collectors.groupingBy(DeptBean::getDdParentId));

        if (DingdingEventTypeConstants.ORG_DEPT_CREATE.equals(eventType)) {
            List<DeptBean> addDepts = new ArrayList<>();
            depts.forEach(d -> {
                // 判断是否存在本身,存在不新增
                if (!longDeptBeanMap.containsKey(d.getDdDeptId())) {
                    // 判断父部门是否存在
                    if (longDeptBeanMap.containsKey(d.getDdParentId())) {
                        DeptBean pDeptBean = longDeptBeanMap.get(d.getDdParentId());
                        d.setParentId(pDeptBean.getDeptId());
                        d.setAncestors(pDeptBean.getAncestors() + "," + pDeptBean.getDeptId());
                        addDepts.add(d);
                    }
                } else {
                    log.info("【钉钉部门新增事件】部门已存在！");
                }
            });
            if (!depts.isEmpty()) {
                deptMapper.insertBatchDept(addDepts);
                log.info("【钉钉部门新增事件】部门新增成功！{}", JSON.toJSONString(depts));
            }
        } else if (DingdingEventTypeConstants.ORG_DEPT_MODIFY.equals(eventType)) {
            // 判断是否有子部门
            // 只有部门父部门修改或部门名称修改的情况才操作
            depts.forEach(d -> {
                if (longDeptBeanMap.containsKey(d.getDdDeptId())) {
                    DeptBean origDept = longDeptBeanMap.get(d.getDdDeptId());
                    origDept.setDeptName(d.getDeptName());
                    origDept.setUpdateTime(new Date());
                    // 判断父部门是否修改
                    if (!origDept.getDdParentId().equals(d.getDdParentId())) {
                        if (longDeptBeanMap.containsKey(d.getDdParentId())) {
                            DeptBean pDept = longDeptBeanMap.get(d.getDdParentId());
                            String origAncestor = origDept.getAncestors();
                            String ancestors = pDept.getAncestors() + "," + pDept.getDeptId();

                            origDept.setParentId(pDept.getDeptId());
                            origDept.setAncestors(ancestors);
                            origDept.setDdParentId(d.getDdParentId());
                            // 查询所有子部门
                            List<Long> childIds = new ArrayList<>();
                            getAllChildByDeptId(origDept, childIds, longListMap);
                            // 更新子部门
                            if (!childIds.isEmpty()) {
                                deptMapper.updatePreAncestorsByDeptId(ancestors, origAncestor, childIds);
                                log.info("【钉钉部门修改事件】子部门更新成功！{}", JSON.toJSONString(childIds));
                            }
                        }
                    }
                    deptMapper.updateDept(origDept);
                    log.info("【钉钉部门修改事件】部门更新成功！{}", JSON.toJSONString(origDept));
                }
            });
        } else if (DingdingEventTypeConstants.ORG_DEPT_REMOVE.equals(eventType)) {
            depts.forEach(d -> {
                if (longDeptBeanMap.get(d.getDdDeptId()) != null) {
                    if (longDeptBeanMap.get(d.getDdDeptId()).getDdParentId() != null) {
                        d.setDdParentId(longDeptBeanMap.get(d.getDdDeptId()).getDdParentId());
                    } else {
                        d.setDdParentId(0L);
                    }
                    d.setDeptId(longDeptBeanMap.get(d.getDdDeptId()).getDeptId());
                } else {
                    d.setDdParentId(0L);
                }
            });

            // 删除部门及其子部门
            depts.forEach(d -> {
                List<Long> childIds = new ArrayList<>();
//                childIds.add(longDeptBeanMap.get(d.getDdDeptId()).getDeptId());
                getAllChildByDeptId(d, childIds, longListMap);
                deptMapper.deleteDeptByIds(childIds);
                log.info("【钉钉部门删除事件】部门删除成功！{}", JSON.toJSONString(childIds));
            });
        }
    }

    /**
     * 根据子部门map递归查询部门所有子部门id列表
     * @param dept 该参数内的子部门列表无值
     * @param child
     * @param longChildMap 每个部门对应的子部门列表map
     */
    public void getAllChildByDeptId(DeptBean dept, List<Long> child, Map<Long, List<DeptBean>> longChildMap) {
        child.add(dept.getDeptId());
        if (longChildMap.get(dept.getDdDeptId()) != null && !longChildMap.get(dept.getDdDeptId()).isEmpty()) {
            for (DeptBean DeptBean : longChildMap.get(dept.getDdDeptId())) {
                getAllChildByDeptId(DeptBean, child, longChildMap);
            }
        }
    }

    /**
     *
     * @param pDept 该参数内的子部门列表是预先有值的
     * @param child
     * @param longDeptBeanMap key为部门ddDeptId，value为具体实体类，方便查询用
     */
    private void getAllChildDeptId(DeptBean pDept, List<Long> child, Map<Long, DeptBean> longDeptBeanMap) {
        if (pDept.getChildren() != null) {
            for (DeptBean childDept : pDept.getChildren()) {
                if (longDeptBeanMap.containsKey(childDept.getDdDeptId())) {
                    child.add(longDeptBeanMap.get(childDept.getDdDeptId()).getDeptId());
                }
                getAllChildDeptId(childDept, child, longDeptBeanMap);
            }
        }
    }

    public static void main(String[] args) {
        String str = "[{\"children\":[],\"ddDeptId\":545525628,\"ddParentId\":545550593,\"deptName\":\"北美B组\",\"params\":{}},{\"children\":[],\"ddDeptId\":545550593,\"ddParentId\":716854208,\"deptName\":\"北美运营部\",\"params\":{}},{\"children\":[],\"ddDeptId\":101313452,\"ddParentId\":1,\"deptName\":\"跨境电商运营中心\",\"params\":{}},{\"children\":[],\"ddDeptId\":545100864,\"ddParentId\":101313461,\"deptName\":\"北美A组\",\"params\":{}},{\"children\":[],\"ddDeptId\":545827076,\"ddParentId\":545583620,\"deptName\":\"欧洲运营部\",\"params\":{}},{\"children\":[],\"ddDeptId\":721661167,\"ddParentId\":101313452,\"deptName\":\"拼多多运营\",\"params\":{}},{\"children\":[],\"ddDeptId\":721490487,\"ddParentId\":101313452,\"deptName\":\"沃尔玛运营\",\"params\":{}},{\"children\":[],\"ddDeptId\":481296651,\"ddParentId\":1,\"deptName\":\"品牌运营中心\",\"params\":{}},{\"children\":[],\"ddDeptId\":545253737,\"ddParentId\":481296651,\"deptName\":\"品牌创意部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545463623,\"ddParentId\":481296651,\"deptName\":\"品牌营销部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545800075,\"ddParentId\":481296651,\"deptName\":\"品牌设计部\",\"params\":{}},{\"children\":[],\"ddDeptId\":486535033,\"ddParentId\":1,\"deptName\":\"供应链管理中心\",\"params\":{}},{\"children\":[],\"ddDeptId\":545031690,\"ddParentId\":486535033,\"deptName\":\"商品订单部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545048760,\"ddParentId\":486535033,\"deptName\":\"品质管理部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545105839,\"ddParentId\":486535033,\"deptName\":\"仓储物流部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545210695,\"ddParentId\":486535033,\"deptName\":\"采购履行部\",\"params\":{}},{\"children\":[],\"ddDeptId\":545307795,\"ddParentId\":486535033,\"deptName\":\"商品开发部\",\"params\":{}},{\"children\":[],\"ddDeptId\":101313454,\"ddParentId\":1,\"deptName\":\"行政管理部\",\"params\":{}},\n" +
                "{\"children\":[],\"ddDeptId\":721215985,\"ddParentId\":101313454,\"deptName\":\"北美C组\",\"params\":{}},\n" +
                "{\"children\":[],\"ddDeptId\":101313461,\"ddParentId\":1,\"deptName\":\"战略管理部\",\"params\":{}},{\"children\":[],\"ddDeptId\":150578897,\"ddParentId\":1,\"deptName\":\"财务管理部\",\"params\":{}},{\"children\":[],\"ddDeptId\":716854208,\"ddParentId\":1,\"deptName\":\"IT信息部\",\"params\":{}},\n" +
                "{\"children\":[],\"ddDeptId\":545583620,\"ddParentId\":716854208,\"deptName\":\"亚马逊运营\",\"params\":{}}" +
                "]";
        List<DeptBean> DeptBeanList = JSON.parseArray(str, DeptBean.class);
    }
}
